package com.viroyal.monitorlib.screenshot;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import com.suntiago.baseui.utils.log.Slog;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 截图处理
 */
public class Shotter {

    private final SoftReference<Context> mRefContext;
    private ImageReader mImageReader;

    private MediaProjection mMediaProjection;
    private VirtualDisplay mVirtualDisplay;

    private String mLocalUrl = "";

    private OnShotListener mOnShotListener;
    int mHeight;
    int mWidth;
    private MediaProjectionManager service;
    private AsyncTask<Image, Void, Bitmap> saveTask;


    public Shotter(Context context, int reqCode, Intent data) {
        this.mRefContext = new SoftReference<>(context);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

            Slog.d("Screenshot :", "reqCode :" + reqCode + "" + "intent :" + data.toString());
            try {
                mMediaProjection = getMediaProjectionManager().getMediaProjection(reqCode, data);
            } catch (Exception e) {
                e.printStackTrace();
            }

            WindowManager window = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            Display mDisplay = window.getDefaultDisplay();
            DisplayMetrics metrics = new DisplayMetrics();
            mDisplay.getRealMetrics(metrics);
            mWidth = metrics.widthPixels;//size.x;
            mHeight = metrics.heightPixels;//size.y;

            mImageReader = ImageReader.newInstance(
                    mWidth,
                    mHeight,
                    PixelFormat.RGBA_8888,//此处必须和下面 buffer处理一致的格式 ，RGB_565在一些机器上出现兼容问题。
                    1);
        }
    }


    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void virtualDisplay() {
        Slog.d("Screenshot :","virtualDisplay");
        mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
                mWidth,
                mHeight,
                Resources.getSystem().getDisplayMetrics().densityDpi,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mImageReader.getSurface(), null, null);

    }

    public void startScreenShot(OnShotListener onShotListener, String loc_url) {
        mLocalUrl = loc_url;
        startScreenShot(onShotListener);
    }


    @TargetApi(Build.VERSION_CODES.KITKAT)
    public void startScreenShot(OnShotListener onShotListener) {
        mOnShotListener = onShotListener;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

            Slog.d("Screenshot :", "startScreenShot");

            virtualDisplay();

            Handler handler = new Handler();

            handler.postDelayed(() -> {
                        Image image = mImageReader.acquireLatestImage();
                        if (saveTask == null) {
                            saveTask = new SaveTask().execute(image);
                        }
                    },
                    500);
            //这里delay 时间过短容易导致 系统权限弹窗的阴影还没消失就完成了截图。 @see<a href="https://github
            // .com/weizongwei5/AndroidScreenShot_SysApi/issues/4">issues</a>
        }
    }

    /**
     * 用完销毁task,防止泄露
     */
    public void cancelTask() {
        saveTask.cancel(true);
        saveTask = null;
    }


    public class SaveTask extends AsyncTask<Image, Void, Bitmap> {

        @TargetApi(Build.VERSION_CODES.KITKAT)
        @Override
        protected Bitmap doInBackground(Image... params) {
            Slog.d("Screenshot :", "SaveTask");
            if (params == null || params.length < 1 || params[0] == null) {
                return null;
            }

            Image image = params[0];

            int width = image.getWidth();
            int height = image.getHeight();
            final Image.Plane[] planes = image.getPlanes();
            final ByteBuffer buffer = planes[0].getBuffer();
            //每个像素的间距
            int pixelStride = planes[0].getPixelStride();
            //总的间距
            int rowStride = planes[0].getRowStride();
            int rowPadding = rowStride - pixelStride * width;
            Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height,
                    Bitmap.Config.ARGB_8888);//虽然这个色彩比较费内存但是 兼容性更好
            bitmap.copyPixelsFromBuffer(buffer);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
            image.close();
            File fileImage = null;
            if (bitmap != null) {
                if (TextUtils.isEmpty(mLocalUrl)) {
                    //生成路径
                    String root = Environment.getExternalStorageDirectory() + "/capture/";
                    String dirName = "monitor";
                    File appDir = new File(root, dirName);
                    if (!appDir.exists()) {
                        appDir.mkdirs();
                    }
                    Slog.d("CaptureUtils  bitmapPath=", appDir.getPath());
                    //文件名为时间
                    long timeStamp = System.currentTimeMillis();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
                    String sd = sdf.format(new Date(timeStamp));
                    String fileName = sd + "-" + timeStamp + ".png";

                    //获取文件
                    File file = new File(appDir, fileName);
                    mLocalUrl = file.getPath();
                    FileOutputStream fos = null;
                    Slog.d("CaptureUtils  FilePath=", file.getPath());
                    try {
                        fos = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.PNG, 80, fos);
                        fos.flush();
                        mOnShotListener.onFinish(mLocalUrl);
                    } catch (Exception e) {
                        e.printStackTrace();
                        Slog.e("CaptureUtils Exception", e.getMessage() + "");
                    } finally {
                        try {
                            if (fos != null) {
                                fos.close();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                            Slog.e("CaptureUtils IOException2", e.getMessage() + "");
                        }
                    }
                }
            } else {
                Slog.d("Screenshot :", "SaveTask error");
                mOnShotListener.onerror();
            }
            if (fileImage != null) {
                return bitmap;
            }
            return null;
        }

        @TargetApi(Build.VERSION_CODES.KITKAT)
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);

            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }

            if (mVirtualDisplay != null) {
                mVirtualDisplay.release();
            }
            if (mMediaProjection != null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    mMediaProjection.stop();
                }
            }

            if (mOnShotListener != null) {
                Log.d("Shotter path:", mLocalUrl + "");

            }

        }
    }


    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private MediaProjectionManager getMediaProjectionManager() {
        if (service == null) {
            service = (MediaProjectionManager) getContext().getSystemService(
                    Context.MEDIA_PROJECTION_SERVICE);
        }
        return service;
    }

    private Context getContext() {
        return mRefContext.get();
    }


    private int getScreenWidth() {
        return Resources.getSystem().getDisplayMetrics().widthPixels;
    }

    private int getScreenHeight() {
        return Resources.getSystem().getDisplayMetrics().heightPixels;
    }


    // a  call back listener
    public interface OnShotListener {
        void onFinish(String path);

        void onerror();
    }
}
